#pragma once
#include <cuda_runtime.h>
#include <glm/glm.hpp>

namespace PhysLeo {

/**
 * static peridynamic stvk material.
 * \f$ g=h=(\frac{x^2-1}{2})^2 , G=1\f$.
 */
template<typename T>
class PdmStvk {
public:
    /**
    * g function in Pdm stvk material is \f$ (\frac{x^2-1}{2})^2 \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
	__host__ __device__ static T gFunction(T x, T* ptr_material)
	{
        auto x2 = x * x;
        return (x2 - 1.0f)*(x2 - 1.0f) / 4.0f;
	}

    /**
    * h function in Pdm stvk material is \f$ (\frac{x^2-1}{2})^2 \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T hFunction(T x, T* ptr_material)
    {
        auto x2 = x * x;
        return (x2 - 1.0f)*(x2 - 1.0f) / 4.0f;
    }

    /**
    * first derivative of g function in Pdm stvk material is \f$ (x^2-1)x \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T dgFunction(T x, T* ptr_material)
    {
        return (x*x - 1)*x;
    }

    /**
    * first derivative of h function in Pdm stvk material is \f$ (x^2-1)x \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T dhFunction(T x, T* ptr_material)
    {
        return (x*x - 1)*x;
    }

    /**
    * second derivative of g function in Pdm stvk material is \f$ 3x^2-1 \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
	__host__ __device__ static T ddgFunction(T x, T* ptr_material)
	{
        return 3.0f*x*x - 1.0f;
	}

    /**
    * second derivative of h function in Pdm stvk material is \f$ 3x^2-1 \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T ddhFunction(T x, T* ptr_material)
    {
        return 3.0f*x*x - 1.0f;
    }

    /**
    * anisotropic function for Pdm stvk material, it is isotropic.
    * @param[in] dir  bond direction in material space
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T anisoWeight(glm::tvec3<T> dir, T* ptr_material)
    {
        return 1.0f;
    }
};

}